@file:Suppress("UNCHECKED_CAST")

package com.test.demoapp.util

import android.content.Context
import android.content.SharedPreferences
import android.text.TextUtils
import com.google.gson.Gson
import com.google.gson.JsonArray
import com.google.gson.JsonParser
import com.test.demoapp.DemoApp

/**
 * 默认 SP 文件。
 */
private const val SP_FILE_COMMON = "demo_system_config"

/**
 * 获取特定 SP 条目的值。
 */
@JvmOverloads
fun <T> getSpValue(
    context: Context = DemoApp.getInstance().applicationContext,
    filename: String = SP_FILE_COMMON,
    key: String,
    defaultVal: T
): T {
    val sp = context.getSp(filename)
    return when (defaultVal) {
        is Boolean -> sp.getBoolean(key, defaultVal) as T
        is String -> sp.getString(key, defaultVal) as T
        is Int -> sp.getInt(key, defaultVal) as T
        is Long -> sp.getLong(key, defaultVal) as T
        is Float -> sp.getFloat(key, defaultVal) as T
        is Set<*> -> sp.getStringSet(key, defaultVal as Set<String>) as T
        else -> throw IllegalArgumentException("Unrecognized default value $defaultVal")
    }
}

@JvmOverloads
fun <T> getSpListValue(
    key: String,
    cls: Class<T>, context: Context = DemoApp.getInstance().applicationContext,
    filename: String = SP_FILE_COMMON
): List<T> {
    val sp = context.getSp(filename)
    var list = ArrayList<T>()
    var json = sp.getString(key, "");
    if (json != null&&!TextUtils.isEmpty(json)) {
        var gson = Gson();
        var array = JsonParser().parse(json).asJsonArray
        array.forEach() {
            list.add(gson.fromJson(it, cls));
        }
    }
    return list;
}


@JvmOverloads
fun <T> getSpMapValue(
    context: Context = DemoApp.getInstance().applicationContext,
    filename: String = SP_FILE_COMMON,
    key: String,
    cls: Class<T>
): Map<String, T> {
    val sp = context.getSp(filename)
    var json = sp.getString(key, "");
    var map = mutableMapOf<String, T>()
    if (json != null&&!TextUtils.isEmpty(json)) {
        val gson = Gson();
        var obj = JsonParser().parse(json).asJsonObject
        var entrySet = obj.entrySet();
        entrySet.forEach {
            var entryKey = it.key
            var value = it.value
            map.put(entryKey, gson.fromJson(value, cls));
        }
    }
    return map;
}

/**
 * 修改单条 SP 记录。如需修改多条或清空SP，推荐使用 [editSp]。
 */
@JvmOverloads
fun <T> putSpValue(
    context: Context = DemoApp.getInstance().applicationContext,
    filename: String = SP_FILE_COMMON,
    key: String,
    value: T
) {
    val editor = context.getSp(filename).edit()

    when (value) {
        is Boolean -> editor.putBoolean(key, value)
        is String -> editor.putString(key, value)
        is Int -> editor.putInt(key, value)
        is Long -> editor.putLong(key, value)
        is Float -> editor.putFloat(key, value)
        is Set<*> -> editor.putStringSet(key, value as Set<String>)
        is List<*> -> {
            var array = JsonArray()
            var gson = Gson();
            for (element in value) {
                var obj = gson.toJsonTree(element);
                array.add(obj);
            }
            editor.putString(key, array.toString());
        }
        is Map<*, *> -> {
            var gson = Gson()
            var json = gson.toJson(value)
            editor.putString(key, json)
        }
        else -> throw UnsupportedOperationException("Unrecognized value $value")
    }

    editor.apply()
}


/**
 * 批量修改或清空 SP。
 */
@JvmOverloads
fun editSp(
    context: Context = DemoApp.getInstance().applicationContext,
    filename: String = SP_FILE_COMMON,
    action: (SharedPreferences.Editor) -> Unit
) {
    context.getSp(filename).edit().apply(action).apply()
}